import logging

from rest_framework import serializers

from customauth.models import MyUser
from naryad.models import (
    Container,
    Images,
    It_lab,
    Patient,
    Pl_uslp,
    Sdl_set,
    Spr_lpu,
    Spr_opl,
    Spr_sdl,
    User_sdl,
)


class UserSerializer(serializers.HyperlinkedModelSerializer):
    short_name = serializers.CharField(source="get_short_name", read_only=True)

    class Meta:
        model = MyUser
        fields = ("login", "mpp", "fam", "im", "ot", "is_active", "is_admin", "short_name")


class ContainerSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Container
        fields = ("id", "used", "nkv")


class Spr_lpuSerializer(serializers.Serializer):  # noqa: N801
    id = serializers.IntegerField(read_only=True)  # noqa: A003
    lpu = serializers.IntegerField()
    name_lpu = serializers.CharField(max_length=100)
    adress = serializers.CharField(max_length=100)
    dred = serializers.DateField(read_only=True)

    def create(self, validated_data) -> Spr_lpu:
        if Spr_lpu.objects.filter(lpu=validated_data["lpu"]).exists():
            return Spr_lpu.objects.get(lpu=validated_data["lpu"])
        return Spr_lpu.objects.create(**validated_data)

    def update(self, instance, validated_data):  # noqa: ANN201
        lpu_data = validated_data.pop("lpu")
        Spr_lpu(name_sdl=lpu_data["sdl"], sdl=lpu_data["name_sdl"]).save()
        return instance


class PatientSerializer(serializers.Serializer):
    id = serializers.IntegerField(read_only=True)  # noqa: A003
    uid = serializers.CharField(max_length=20)
    fam = serializers.CharField(max_length=50)
    im = serializers.CharField(max_length=50)
    ot = serializers.CharField(max_length=50, allow_blank=True, default="")
    dr = serializers.DateField()
    adress = serializers.CharField(max_length=100)
    dred = serializers.DateField(read_only=True)

    def create(self, validated_data) -> Patient | None:
        try:
            Patient.objects.create(**validated_data)
        except Exception:
            logging.exception("Found an error")
            return Patient.objects.create(**validated_data)

    def update(self, instance, validate_data) -> Patient | None:
        try:
            instance.uid = validate_data.get("uid", instance.uid)
            instance.fam = validate_data.get("fam", instance.fam)
            instance.im = validate_data.get("im", instance.im)
            instance.ot = validate_data.get("ot", instance.ot)
            instance.dr = validate_data.get("dr", instance.dr)
            instance.adress = validate_data.get("adress", instance.adress)
            instance.save()
        except Exception:
            logging.exception("Found an error")
            return Patient.objects.create(**validate_data)


class Spr_oplSerializer(serializers.Serializer):  # noqa: N801
    id = serializers.IntegerField(read_only=True)  # noqa: A003
    opl = serializers.IntegerField()
    name_opl = serializers.CharField(max_length=100)
    dred = serializers.DateField(read_only=True)

    def create(self, validated_data) -> Spr_opl | None:
        try:
            Spr_opl.objects.create(**validated_data)
        except Exception:
            logging.exception("Found an error")
            return Spr_opl.objects.create(**validated_data)

    def update(self, instance, validate_data) -> Spr_opl | None:
        try:
            instance.opl = validate_data.get("opl", instance.opl)
            instance.name_opl = validate_data.get("name_opl", instance.name_opl)
            instance.save()
        except Exception:
            logging.exception("Found an error")
            return Spr_opl.objects.create(**validate_data)


class Spr_sdlSerializer(serializers.Serializer):  # noqa: N801
    id = serializers.IntegerField(read_only=True)  # noqa: A003
    sdl = serializers.IntegerField()
    name_sdl = serializers.CharField(max_length=100)
    dred = serializers.DateField(read_only=True)

    def create(self, validated_data) -> Spr_sdl | None:
        try:
            Spr_sdl.objects.create(**validated_data)
        except Exception:
            logging.exception("Found an error")
            return Spr_sdl.objects.create(**validated_data)

    def update(self, instance, validate_data) -> Spr_sdl | None:
        try:
            instance.sdl = validate_data.get("sdl", instance.sdl)
            instance.name_sdl = validate_data.get("name_sdl", instance.name_sdl)
            instance.save()
        except Exception:
            logging.exception("Found an error")
            return Spr_sdl.objects.create(**validate_data)


class Sdl_setSerializer(serializers.ModelSerializer):  # noqa: N801
    class Meta:
        model = Sdl_set
        fields = ("id", "doc", "tech", "lit", "pol", "cadcam", "dred")


class User_sdlSerializer(serializers.ModelSerializer):  # noqa: N801
    user_full = UserSerializer(source="user", many=False)

    class Meta:
        model = User_sdl
        fields = ("id", "user", "sdls", "access", "lpu", "user_full")


class ImagesSerializer(serializers.ModelSerializer):
    class Meta:
        model = Images
        fields = ("id", "etap", "img")


class Pl_uslpSerializer(serializers.ModelSerializer):  # noqa: N801
    class Meta:
        model = Pl_uslp
        fields = "__all__"


class It_labTwoSerializer(serializers.ModelSerializer):  # noqa: N801
    fio_short = UserSerializer(source="MyUser", many=False)

    class Meta:
        model = It_lab
        fields = (
            "id",
            "lpu",
            "patient",
            "opl",
            "sdl_etap",
            "sdl_set",
            "idkv",
            "nkv",
            "dou",
            "dzr",
            "stu",
            "sris",
            "id_etap",
            "dnaz_etap",
            "fio_short",
        )


class It_labSerializer(serializers.Serializer):  # noqa: N801
    id = serializers.IntegerField(read_only=True)  # noqa: A003
    lpu = Spr_lpuSerializer(many=False)
    patient = PatientSerializer(many=False)
    opl = Spr_oplSerializer(many=False)
    sdl_etap = Spr_sdlSerializer(many=False)
    sdl_set = Sdl_setSerializer(many=False)
    naryad_doc = User_sdlSerializer(many=False)
    user_etap_link = UserSerializer(many=False)
    container = ContainerSerializer(many=False)

    idkv = serializers.IntegerField()
    nkv = serializers.IntegerField()
    dou = serializers.DateField()
    dzr = serializers.DateField(required=False)
    stu = serializers.FloatField()
    sris = serializers.IntegerField()
    id_etap = serializers.IntegerField()
    dnaz_etap = serializers.DateField(required=False)
    dn_etap = serializers.DateField(required=False)
    user_etap = serializers.CharField(required=False, max_length=40, default="")
    mpp_etap = serializers.IntegerField()
    kom_etap = serializers.CharField(max_length=100, required=False)

    # level for serialization

    def create(self, validated_data) -> It_lab:  # noqa: PLR0912, C901
        if It_lab.objects.filter(idkv=validated_data["idkv"], id_etap=validated_data["id_etap"]).exists():
            if Pl_uslp.objects.filter(idkv=validated_data["idkv"]).exists():
                return It_lab.objects.filter(idkv=validated_data["idkv"]).last()
            for usl in validated_data["uslugi"]:
                Pl_uslp.objects.create(idkv=validated_data["idkv"], **usl)
            return It_lab.objects.filter(idkv=validated_data["idkv"]).last()
        try:
            lpu_data = validated_data.pop("lpu")
            if Spr_lpu.objects.filter(lpu=lpu_data["lpu"]).exists():
                lpu = Spr_lpu.objects.get(lpu=lpu_data["lpu"])
            else:
                lpu = Spr_lpu.objects.create(**lpu_data)
            patient_data = validated_data.pop("patient")
            if Patient.objects.filter(uid=patient_data["uid"]).exists():
                patient = Patient.objects.get(uid=patient_data["uid"])
            else:
                patient = Patient.objects.create(**patient_data)
            opl_data = validated_data.pop("opl")
            if Spr_opl.objects.filter(opl=opl_data["opl"]).exists():
                opl = Spr_opl.objects.get(opl=opl_data["opl"])
            else:
                opl = Spr_opl.objects.create(**opl_data)
            sdl_etap_data = validated_data.pop("sdl_etap")
            if Spr_sdl.objects.filter(sdl=sdl_etap_data["sdl"]).exists():
                sdl_etap = Spr_sdl.objects.get(sdl=sdl_etap_data["sdl"])
            else:
                sdl_etap = Spr_sdl.objects.create(**sdl_etap_data)
            sdl_set_data = validated_data.pop("sdl_set")
            sdl_set = Sdl_set.objects.create(**sdl_set_data)
            container = Container.objects.get(id=0)
            it_lab = It_lab.objects.create(
                lpu=lpu,
                patient=patient,
                opl=opl,
                sdl_etap=sdl_etap,
                sdl_set=sdl_set,
                container=container,
                **validated_data,
            )
            for usl in validated_data["uslugi"]:
                Pl_uslp.objects.create(idkv=validated_data["idkv"], **usl)
        except Exception:
            logging.exception("Fount an error")
            return It_lab.objects.create(**validated_data)
        else:
            return it_lab

    def update(self, instance, validate_data):  # noqa: ANN201
        try:
            instance.lpu = validate_data.get("lpu", instance.lpu)
            instance.patient = validate_data.get("patient", instance.patient)
            instance.idkv = validate_data.get("idkv", instance.idkv)
            instance.nkv = validate_data.get("nkv", instance.nkv)
            instance.dou = validate_data.get("dou", instance.dou)
            instance.dzr = validate_data.get("dzr", instance.dzr)
            instance.stu = validate_data.get("stu", instance.stu)
            instance.opl = validate_data.get("opl", instance.opl)
            instance.sris = validate_data.get("sris", instance.sris)
            instance.id_etap = validate_data.get("id_etap", instance.id_etap)
            instance.dnaz_etap = validate_data.get("dnaz_etap", instance.dnaz_etap)
            instance.dn_etap = validate_data.get("dn_etap", instance.dn_etap)
            instance.dz_etap = validate_data.get("dz_etap", instance.dz_etap)
            instance.user_etap = validate_data.get("user_etap", instance.user_etap)
            instance.mpp_etap = validate_data.get("mpp_etap", instance.mpp_etap)
            instance.sdl_etap = validate_data.get("sdl_etap", instance.sdl_etap)
            instance.kom_etap = validate_data.get("kom_etap", instance.kom_etap)
            instance.sdl_set = validate_data.get("sdl_set", instance.sdl_set)
            instance.save()
            if Pl_uslp.objects.filter(idkv=validate_data["idkv"]).exists():
                return instance
            for usl in validate_data["uslugi"]:
                Pl_uslp.objects.create(idkv=validate_data["idkv"], **usl)
        except Exception:
            logging.exception("Found an error")
            return It_lab.objects.create(**validate_data)
        else:
            return instance
